package storage

import "time"

// Storager 缓存驱动统一接口
type Storager interface {
	// Scan 获取键对应的值, 并解码到 refVal
	//   - refVal 是一个指向具体数据类型的指针, 用于存放反序列化后的数据
	//   - 不存在或已经过期或反序列化失败则返回错误
	//   - 标量类型直接解析到 refVal
	//   - 其他返回数据为 msgpack 自动反序列化后解析到 refVal
	Scan(key string, refVal any) error
	// Get 获取键对应的值
	//   - 不存在或如果已经过期则返回错误
	//   - 存在则返回缓存值:
	//   - - 标量类型直接返回 Any 缓存数据值
	//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
	Get(key string) (any, error)
	// GetEntry 获取键对应的缓存项副本信息, 如果不存在或已经过期则返回错误
	GetEntry(key string) (entry *Entry, err error)
	// GetOrSet 获取键对应的值, 如不存在则设置为指定的值
	//   - 不存在或如果已经过期则进行设置并返回设置的值
	//   - 存在则返回旧值:
	//   - - 标量类型直接返回 Any 缓存数据值
	//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
	GetOrSet(key string, value any, opts ...EntryOptions) (any, error)
	// GetAndSet 获取键对应的旧值并设置新值
	//   - 不存在或如果已经过期则返回nil
	//   - 存在则返回旧值:
	//   - - 标量类型直接返回 Any 缓存数据值
	//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
	GetAndSet(key string, value any, opts ...EntryOptions) (any, error)
	// GetAndDelete 获取键对应的值, 并删除该键
	//   - 不存在或如果已经过期则返回错误
	//   - 存在则返回值:
	//   - - 标量类型直接返回 Any 缓存数据值
	//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
	GetAndDelete(key string) (any, error)

	// GetTags 获取所有Tag标签
	GetTags() []string
	// GetTagKeys 获取指定 Tag 标签对应的所有缓存 Keys 键名
	GetTagKeys(tag string) []string
	// GetKeyTags 获取指定键名 Key 对应的所有缓存 Tags 标签
	GetKeyTags(key string) []string

	// Set 设置键值对, 可以通过 EntryOption 设置 Expire, Tag 等选项
	//   - key 为空 或 value 为nil 则返回错误
	//   - 如缓存 key 已存在且 opts 为空, 则保持过期时间Tags等选项
	//   - 如缓存 key 已存在且 opts 不为空, 则更新过期时间Tags等opts选项(原Tag保留, 如有新Tag则追加)
	//   - 如缓存 key 不存在且 opts 为空, 则使用默认选项存储数据
	//   - 如缓存 key 不存在且 opts 不为空, 则使用opts选项存储数据
	Set(key string, value any, opts ...EntryOptions) error
	// SetWithExists 仅当缓存 Key 键存在时才更新设置值, 返回True表示更新成功
	SetWithExists(key string, value any, opts ...EntryOptions) (updated bool, err error)
	// SetWithNotExists 仅当缓存 Key 键不存在时才设置值, 返回True表示设置成功
	SetWithNotExists(key string, value any, opts ...EntryOptions) (added bool, err error)
	// Incr 原子性地将键对应的值增加+1, 并返回新的值
	//   - 如果键不存在, 则将原子值设为 1
	//   - 如果键存在, 则更新值 +1
	Incr(key string, opts ...EntryOptions) (int64, error)
	// IncrBy 原子性地将键对应的值增加 Step 步进值, 并返回新的值
	//   - 如果键不存在, 则将原子值设为 Step
	//   - 如果键存在, 则更新值 +Step
	IncrBy(key string, step int64, opts ...EntryOptions) (int64, error)
	// Decr 原子性地将键对应的值减少 -1, 并返回新的值
	//   - 如果键不存在, 则将原子值设为 -1
	//   - 如果键存在, 则更新值 -1
	Decr(key string, opts ...EntryOptions) (int64, error)
	// DecrBy 原子性地将键对应的值减少 Step 步进值, 并返回新的值
	//   - 如果键不存在, 则将原子值设为 -Step
	//   - 如果键存在, 则更新值 -Step
	DecrBy(key string, step int64, opts ...EntryOptions) (int64, error)

	// SStringAdd 向指定 key 的 String 集合添加一个或多个成员元素
	//   - 如果指定 key 的集合不存在, 则新建集合并添加值到集合
	//   - 如果指定 key 不是一个 String 集合, 则返回错误
	//   - 如果指定 key 的集合存在, 则添加值到集合
	//   - 如果 items为空, 则什么也不做, 直接返回nil
	SStringAdd(key string, items ...string) error
	// SStringRemove 从指定 key 的 String 集合中移除一个或多个成员
	//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
	//   - 如果items为空, 则什么也不做, 直接返回nil
	SStringRemove(key string, items ...string) error
	// SStringClear 清空指定 key 的 String 集合
	//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
	SStringClear(key string) error
	// SStringContains 判断一个或多个成员是否全部在指定 key 的 String 集合中
	//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回 false
	//   - 查询多个成员, 任意一个成员不在集合中, 则返回 false
	SStringContains(key string, items ...string) bool
	// SStringContainsSome 判断一个或多个成员的中任意一个成员是否在指定 key 的 String 集合中
	//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回 false
	//   - 查询多个成员, 任意一个成员存在集合中, 则返回 true
	SStringContainsSome(key string, items ...string) bool
	// SStringMembers 获取指定 key 的 String 集合的所有成员
	//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
	SStringMembers(key string) ([]string, error)
	// SStringTraverse 遍历指定 key 的 String 集合的所有成员
	//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
	//   - fn 签名是 iter.Seq[string], 迭代过程中, 返回 false 则停止遍历
	SStringTraverse(key string, fn func(string) bool) error
	// SStringSize 获取指定 key 的 String 集合的成员数量
	//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
	SStringSize(key string) (int64, error)

	// SIntAdd 向指定 key 的 Int64 集合添加一个或多个成员元素
	//   - 如果指定 key 的集合不存在, 则新建集合并添加值到集合
	//   - 如果指定 key 不是一个 Int64 集合, 则返回错误
	//   - 如果指定 key 的集合存在, 则添加值到集合
	//   - 如果 items为空, 则什么也不做, 直接返回nil
	SIntAdd(key string, items ...int64) error
	// SIntRemove 从指定 key 的 Int64 集合中移除一个或多个成员
	//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
	//   - 如果items为空, 则什么也不做, 直接返回nil
	SIntRemove(key string, items ...int64) error
	// SIntClear 清空指定 key 的 Int64 集合
	//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
	SIntClear(key string) error
	// SIntContains 判断一个或多个成员是否全部在指定 key 的 Int64 集合中
	//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回 false
	//   - 查询多个成员, 任意一个成员不在集合中, 则返回 false
	SIntContains(key string, items ...int64) bool
	// SIntContainsSome 判断一个或多个成员的中任意一个成员是否在指定 key 的 Int64 集合中
	//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回 false
	//   - 查询多个成员, 任意一个成员存在集合中, 则返回 true
	SIntContainsSome(key string, items ...int64) bool
	// SIntMembers 获取指定 key 的 Int64 集合的所有成员
	//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
	SIntMembers(key string) ([]int64, error)
	// SIntTraverse 遍历指定 key 的 Int64 集合的所有成员
	//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
	//   - fn 签名是 iter.Seq[int64], 迭代过程中, 返回 false 则停止遍历
	SIntTraverse(key string, fn func(int64) bool) error
	// SIntSize 获取指定 key 的 Int64 集合的成员数量
	//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
	SIntSize(key string) (int64, error)

	// LoadDo 获取键对应的值, 并反序列化解析后赋值到 refVal
	//   - refVal 是一个指向具体类型的指针, 用于存放反序列化后的数据
	//   - 缓存存在: 则反序列化解析后赋值到 refVal
	//   - 缓存不存在: 则执行 Fn 函数获取查询值后设置为缓存(Set Use Opts), 最后赋值到 refVal
	//   - 注意: 请确保 refVal(&T) 的类型和 do() 函数的返回值T类型一致
	LoadDo(key string, refVal any, do func() (setVal any, err error), opts ...EntryOptions) error
	// UpdateFn 更新键对应的值
	//   - 如果键不存在, 则执行 Fn 函数设置值并返回设置的默认值(Set Use Opts), 并返回设置的默认值
	//   - 如果键存在, 则执行 Fn 函数更新值并返回更新的新值(Set Without Opts), 并返回更新的新值
	UpdateFn(key string, fn func(getVal any, exits bool) (updateVal any, err error), opts ...EntryOptions) (any, error)
	// Expire 设置指定缓存 Key 的存活时间(精度为秒)
	Expire(key string, duration time.Duration) error
	// ExpireAt 设置指定缓存 Key 的存活时间(精度为秒)
	ExpireAt(key string, expireAt time.Time) error
	// TTL 获取键的剩余存活时间(精度为秒)
	//   - 不存在或如果已经过期则返回-1
	//   - 如果设置了永久存活则返回0
	TTL(key string) time.Duration
	// Contains 判断缓存 Key 是否存在, 支持多个键查询, 只要有一个键不存在则返回false
	Contains(keys ...string) bool
	// ContainsSome 判断缓存 Key 是否存在, 支持多个键查询, 如果有一个或多个键存在则返回true
	ContainsSome(keys ...string) bool
	// ContainsTags 检查 Tag 标签是否存在, 支持多个键查询, 只要有一个键不存在则返回false
	ContainsTags(tags ...string) bool
	// ContainsSomeTags 检查 Tag 标签是否存在, 支持多个键查询, 如果有一个或多个键存在则返回true
	ContainsSomeTags(tags ...string) bool
	// ContainsTagKey 检查 Tag/Key 标签对是否存在
	ContainsTagKey(tag, key string) bool
	// Metrics 返回监控指标
	Metrics() *Metrics
	// Cleanup 手动清理过期数据
	Cleanup() error
	// Delete 删除一个或多个键
	Delete(keys ...string) error
	// DeleteTags 依据缓存Tag标签删除缓存项, 同时tag 标签以及对应的 key <=> tags 和 tag <=> keys 的索引集合数据
	DeleteTags(tags ...string) error
	// Clear 清空所有数据(同步操作)
	Clear() error
	// ClearAsync 清空所有数据(异步操作)
	ClearAsync() error

	// TotalSize 返回当前缓存的总大小(单位: byte)
	TotalSize() int64
	// TotalCount 返回当前缓存项(Key)的总数量(单位: 个)
	TotalCount() int64
	// MaxSize 返回当前缓存实例的最大容量(单位: byte)
	MaxSize() int64
	// MaxEntrySize 获取单个缓存项数据限制的大小(单位: byte)
	MaxEntrySize() int64
	// StorageType 获取缓存存储驱动类型
	StorageType() StorageType
	// DefaultExpire 获取默认过期时间
	DefaultExpire() time.Duration
	// UseLocal 仅使用 Local 缓存进行操作( 通常为 MemoryCache )
	//   - 仅在 L2Cache 驱动模式下有效, 其他驱动模式返回自身驱动实例
	UseLocal() Storager
	// UseRemote 仅仅使用 Remote 进行缓存操作( 通常为 RedisCache )
	//   - 仅在 L2Cache 驱动模式下有效, 其他驱动模式返回自身驱动实例
	UseRemote() Storager
	// LiveState 获取当前缓存实例的运行状态
	LiveState() LiveState
	// IsGlobal 是否为全局缓存实例
	IsGlobal() bool
	// setGlobal 设置实例为全局缓存标记
	SetGlobal()
}
